/*
    定时器
    1.创建定时器【这是一个文件】
        int fd = timerfd_create(int clockd, int flags) 
            CLOCK_MONTONIC  系统启动时间作为一个递增基准值
    2. 启动定时器
        timerfd_settime(int fd, int flags,const struct itimerspec *new_value, struct itimerspec *old_value) 启动定时器
                                                设置的超时时间                          接收当前定时器原有的超时时间【还原】

    时间轮思想：如定时30s，那么只需要每隔1秒，移动一次指针，若指针指向30处，代表将要超时
                将30秒处，设置为一个回调函数，指针到这里 自动执行
                如何让指针归位？与环形队列是一样的，(指针位置 + 30)%30；
    多轮时间轮：若是时间很大，比如6小时 40分钟34秒的闹钟
                先让小时指针走到6，再让分针走到40，再让秒针走到34，逐级递交参数就可以。 
    二维数组：一维数组明显每次只能执行一个任务【是否可以挂接一个任务队列？】
             二维数组可以对一维进行扩展【vector】，指针指到对应时间再向下依次执行任务。
    **shared_ptr引用计数特性与定时器类： 延迟定时任务执行
            在定时器类中的析构函数内，定义了定时器结束后要执行的函数；
            此外，使用shared_ptr管理这个类，以销毁为例 :
            若无新连接，表示tick数组指针走到ptr处将计数器--，调用析构函数结束
            若有新连接，那么会再创建一个ptr对象，放在数组中，此时ptr=2，当指针同样走到ptr处，计数器--，此时却不是调用析构函数结束，而是走向下一轮。

*/
#include <cstdio>
#include <unistd.h>
#include <fcntl.h>
#include <sys/timerfd.h>
#include <stdint.h>

int main()
{
    int timer_fd = timerfd_create(CLOCK_MONOTONIC, 0); // 0默认阻塞操作
    if(timer_fd < 0)
    {
        perror("timerfd_create err\n");
        return -1;
    }

    struct itimerspec itime;
    itime.it_value.tv_sec = 1; //设置为 1 秒
    itime.it_value.tv_nsec = 0;  //纳秒
    itime.it_interval.tv_sec = 1; //超时 1 秒后，每次的超时时间
    itime.it_interval.tv_nsec = 0;

    timerfd_settime(timer_fd, 0, &itime, nullptr);

    while(1)
    {
        uint64_t times; //超时多少次, 因为定时器在每次超时后，都会在fd中写入一个8字节的计数
        int ret = read(timer_fd, &times, 8);
        if(ret < 0)
        {
            perror("read error\n");
            return -1;
        }
        printf("超时了，距离上一次，超时了%ld次\n",times); //注意 非 行缓冲
    }
    close(timer_fd);
    return 0;
}